#include "stdafx.h"
#include "SimpleMap.h"
#include "Element.h"

#include <fstream>
namespace Core
{
	ActionListener::ActionListener():Base(&ActionListener::OnAction){}
	
	SimpleMap::SimpleMap(std::string filename,int Blockwidth,int BlockHeight)
		:blockwidth(Blockwidth),blockheight(BlockHeight)
	{
		std::ifstream in;
		try{
		in.open(filename.c_str());
		}
		catch(...)
		{
			string p="No such a file ";
			p+=filename;
			throw std::exception(p.c_str());
		}
		unsigned short data;
		int j;
		in>>j;
		width=j;
		in>>j;
		height=j;
		map.resize(width*height);
		for(int i=0;i<height;i++)
			for(int j=0;j<width;j++)
			{
				if(in.eof()) throw std::exception("No enough data");
				in>>data;
				int t=Base::MapInfo::PASS;
				if(data!=(int)(Base::MapInfo::BLOCK) && data!=(int)(Base::MapInfo::PASS) )
					throw std::exception("Not a proper data");
				MapInfo info((MapInfo::Info)data);
				map[i*width+j]=info;
			}
		mLogicMap.Init(this);
	}
	Size SimpleMap::GetBlockSize() 
	{
		return Size(blockwidth,blockheight);
	}
	Size SimpleMap::GetMapSize()
	{
		return Size(width*blockwidth,height*blockheight);
	}
	Size SimpleMap::GetMapSizeByBlock()
	{
		return Size(width,height);
	}
	Position SimpleMap::BlockPosition(const Position& p)
	{
		return Position(p.x / blockwidth,p.y / blockheight);
	}
	Position SimpleMap::GetGridPosition(const Position& p)
	{
		return Position(p.x / blockwidth * blockwidth,p.y / blockheight * blockwidth);
	}
	SimpleMap::MapInfo SimpleMap::GetInfo(const Position& p)
	{
		Position& t=BlockPosition(p);
		return map[t.y*width+t.x];
	}
	void SimpleMap::AddElement(Element* element)
	{
		Position& t=this->BlockPosition (element->GetPosition());
		map[t.y*width+t.x].element=element;
	}
	Element* SimpleMap::GetElement(const Core::Position& position)
	{
		Position& t=this->BlockPosition( position);
		return map[t.y*width+t.x].element;
	}
	void SimpleMap::OnAction(SourceType& source)
	{
		Position& pre=BlockPosition(source.GetPrePosition());
		Position& t=BlockPosition(source.GetPosition());
		map[pre.y*width+pre.x].element=0;
		map[t.y*width+t.x].element=&source;
	}
	Position SimpleMap::GetGridPositionFromBlockPosition (const Core::Position &p)
	{
		return Position(p.x*blockwidth,p.y*blockheight);
	}
	SimpleMap::LogicMap& SimpleMap::GetLogicMap()
	{
		return mLogicMap;
	}

	SimpleMap::LogicMap::LogicMap() 
	{}
	void SimpleMap::LogicMap::Init(Core::SimpleMap* map)
	{
		mMap=map;
	}
	Size SimpleMap::LogicMap::GetMapSize()
	{
		return mMap->GetMapSizeByBlock();
	}
	void SimpleMap::LogicMap::AddElement(Element* element)
	{
		mMap->AddElement(element);
	}
	Element* SimpleMap::LogicMap::GetElement(const Position& p)
	{
		return mMap->map[p.y*mMap->width+p.x].element;
	}
	SimpleMap::MapInfo SimpleMap::LogicMap::GetInfo(const Position&p)
	{
		return mMap->map[p.y*mMap->width+p.x];
	}
	SimpleMap::LogicMap::LogicPart& SimpleMap::LogicMap::GetLogicMap()
	{
		return *this;
	}
}